//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#ifndef __VINCI_LOCK_H__
#define __VINCI_LOCK_H__

#include <engine.h>

class VinciLock
{
public:
    VinciLock()
    {
#ifdef _zener
#elif defined(_wince)
        AuraCriticalSection_Create(&m_lock);
#elif defined(_win32)
        CMutex::New(&m_lock);
#else
# add the code of the new platform
#endif

#ifdef _DEBUG
        m_count = 0;
#endif
    }

    Void *operator new(size_t size, Void* pv) { return pv; }

    Void *operator new(size_t size) { return malloc(size); }

    Void operator delete(Void* pv) { free(pv); }

    ECode Lock()
    {
        WaitResult wr = 0;
        do {
#ifdef _zener
            m_lock.Lock(&wr);
#elif defined(_wince)
            AURA_LOCK(m_lock);
#elif defined(_win32)
            m_lock->Lock(&wr);
#else
# add the code of the platform
#endif
            if (WaitResult_Interrupted == wr) {
                return E_INTERRUPTED;
            }
        } while (WaitResult_OK != wr);

#ifdef _zener
        GFX_EXPRESSION(DEBUG_LOCK, {
            IThread* thread;
            ECode ec = DzGetCurrentThread(&thread);
            if (NOERROR == ec) {
                Int32       id;
                ec = thread->GetId(&id);
                assert(NOERROR == ec);
                kprintf(">>>>this 0x%08x thread id: %d >>>>>>>>>>>lock %d\n",
                    this, id, ++m_count);
                assert(m_count >= 1);
                thread->Release();
            }
        });
#elif defined(_wince)
        GFX_EXPRESSION(DEBUG_LOCK, {
            Int32 id = AuraThread_GetCurrentId();
            kprintf(">>>>this 0x%08x thread id: %d >>>>>>>>>>>lock %d\n",
                this, id, ++m_count);
            assert(m_count >= 1);
        });
#elif defined(_win32)
        GFX_EXPRESSION(DEBUG_LOCK, {
            IThread* thread = CThread::GetCurrent();
            Int32 id;
            ECode ec = thread->GetId(&id);
            assert(NOERROR == ec);
            kprintf(">>>>this 0x%08x thread id: %d >>>>>>>>>>>lock %d\n",
                this, id, ++m_count);
            assert(m_count >= 1);
            });
#else
# add the code of the new platform
#endif

        return NOERROR;
    }

    Void Unlock()
    {
#ifdef _zener
        GFX_EXPRESSION(DEBUG_LOCK, {
            IThread* thread;
            ECode ec = DzGetCurrentThread(&thread);
            if (NOERROR == ec) {
                Int32 id;
                ec = thread->GetId(&id);
                assert(NOERROR == ec);
                kprintf(">>>>this 0x%08x thread id: %d >>>>>>>>>>>unlock %d\n",
                    this, id, --m_count);
                assert(m_count >= 0);
                thread->Release();
            }
        }
        );

        m_lock.Unlock();
#elif defined(_wince)
        GFX_EXPRESSION(DEBUG_LOCK, {
            Int32 id = AuraThread_GetCurrentId();
            kprintf(">>>>this 0x%08x thread id: %d >>>>>>>>>>>unlock %d\n",
                this, id, --m_count);
            assert(m_count >= 0);});

        AURA_UNLOCK(m_lock);

#elif defined(_win32)
        GFX_EXPRESSION(DEBUG_LOCK, {
            IThread* thread = CThread::GetCurrent();
            Int32 id;
            ECode ec = thread->GetId(&id);
            assert(NOERROR == ec);
            kprintf(">>>>this 0x%08x thread id: %d >>>>>>>>>>>unlock %d\n",
                this, id, --m_count);
            assert(m_count >= 0);});

        m_lock->Unlock();
#else
# add the code of the new platform
#endif
    }

public:
#ifdef _zener
    DzMutex m_lock;
#elif _wince
    PVoid   m_lock;
#elif _win32
    IMutex* m_lock;
#else
# add the code of the new platform
#endif

#ifdef _DEBUG
    Int32 m_count;
#endif
};

#endif  // __VINCI_LOCK_H__
